home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
dpmi_lib.zip
/
DPMIUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-06
|
14KB
|
612 lines
/* This file is DPMIUTIL.C
** Copyright (c) Rainer Schnitker 10/91
*/
/* This file need Turbo C to compile,
** but there are only TurboC specials like asm { statement }
** Function used : allocmem(),MK_FP(),FP_SEG(),FP_OFF()
** Compile options : -ms (because of other segments in protected mode)
** -2 (protected mode)
** -B (Assembler lines)
*/
#include "DPMI.H"
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
/* CPU switching for DPMI 0.9 */
void real_to_protected()
{
unsigned int speicherseg;
WORD rax,seg,off,hostreq;
DWORD PM_jump ;
int status;
asm { mov ax,1687h /* DMPI supported ? */
int 2fh
mov rax,ax
mov off,di
mov seg,es
mov hostreq,si }
if (rax){
printf("no dpmi supported\n");
exit(1);
}
PM_jump = (long)seg ;
PM_jump <<= 16 ;
PM_jump += (long)off ;
status=allocmem(hostreq,&speicherseg); /* for DPMI-Stack */
if (status!=-1) { /* reserve */
printf("allocmem() error\n");
exit(1);
}
asm { mov es,speicherseg ;
mov ax,0 ;
call DWORD PTR PM_jump ;
jnc PMOK ; }
printf("Can't switch to Protected Mode!");
exit(1);
PMOK:
printf("CPU in Protected Mode\n");
printf("CS=%X DS=%X ES=%X SS=%X\n",_CS,_DS,_ES,_SS);
_BL=0x23 ; /* Control Break -> protected_to_real() */
_CX=_CS ;
asm mov dx,OFFSET MYINT ;
DPMI(0x0205);
}
void protected_to_real()
{
printf("CPU in Real Mode\n");
asm MYINT LABEL byte ;
asm { mov ax,4C00h
int 21h } /* program ends here */
}
/* LDT Descriptor management services DPMI 0.9 */
WORD AllocLDT(WORD anzahl)
{
_CX=anzahl;
DPMI(0x0000);
asm jnc OKallocldt ;
return 0;
OKallocldt:
return _AX;
}
int FreeLDT(WORD sel)
{
_BX=sel;
DPMI(0x0001);
asm jnc OKfreeldt;
return -1;
OKfreeldt:
return 0;
}
WORD SegtoSel(WORD seg)
{
_BX=seg;
DPMI(0x0002);
asm jnc OKsegsel;
return 0;
OKsegsel:
return _AX;
}
WORD SelInc()
{
DPMI(0x0003);
return _AX ;
}
int LockSel(WORD sel)
{
_BX=sel ;
DPMI(0x0004);
asm jnc OKlocksel;
return -1;
OKlocksel:
return 0;
}
int UnlockSel(WORD sel)
{
_BX=sel ;
DPMI(0x0005);
asm jnc OKunlocksel;
return -1;
OKunlocksel:
return 0;
}
DWORD GetBaseAddress(WORD sel)
{
_BX=sel;
DPMI(0x0006);
asm jnc OKgetbase;
return 0;
OKgetbase:
return ( (DWORD)_DX | ( (DWORD)_CX <<16 ) );
}
int SetBaseAddress(WORD sel,DWORD address)
{
_CX=(WORD) (address>>16);
_DX=(WORD) address ;
_BX=sel;
DPMI(0x0007);
asm jnc OKsetbase;
return -1;
OKsetbase:
return 0;
}
int SetLimit(WORD sel,DWORD limit)
{
_BX=sel;
_CX=(WORD) (limit>>16) ;
_DX=(WORD) limit ;
DPMI(0x0008);
asm jnc OKsetlimit;
return -1;
OKsetlimit:
return 0;
}
int SetAccess(WORD sel,BYTE access,BYTE extaccess)
{
_BX=sel;
_CL=access;
_CH=extaccess;
DPMI(0x0009);
asm jnc OKsetaccess;
return -1;
OKsetaccess:
return 0;
}
WORD CreatAlias(WORD segsel)
{
_BX=segsel;
DPMI(0x000a);
asm jnc OKcreatalias;
return 0;
OKcreatalias:
return _AX ;
}
int GetDescriptor(WORD sel,DESCRIPTOR *d)
{
asm push es ;
_BX=sel;
_ES=FP_SEG(d);
_DI=FP_OFF(d);
DPMI(0x000b);
asm pop es ;
asm jnc OKgetdisc ;
return -1;
OKgetdisc:
return 0;
}
int SetDescriptor(WORD sel,DESCRIPTOR *d)
{
asm push es ;
_BX=sel;
_ES=FP_SEG(d);
_DI=FP_OFF(d);
DPMI(0x000c);
asm pop es ;
asm jnc OKsetdisc ;
return -1;
OKsetdisc:
return 0;
}
int AllocSpecialLDT(WORD sel)
{
_BX=sel;
DPMI(0x000d);
asm jnc OKspecial;
return -1 ;
OKspecial:
return 0 ;
}
/* Interrupt Services DPMI 0.9 */
int GetExceptionVector(BYTE b,WORD *sel,WORD *off)
{
_BL=b;
DPMI(0x0202);
asm jnc OKgetexeption;
return -1;
OKgetexeption:
*sel=_CX;
*off=_DX;
return 0;
}
int SetExceptionVector(BYTE b,WORD sel,WORD off)
{
_BL=b;
_CX= sel;
_DX= off;
DPMI(0x0203);
asm jnc OKsetexeption;
return -1;
OKsetexeption:
return 0;
}
int GetPMinterruptVector(BYTE b,WORD *sel,WORD *off)
{
_BL=b;
DPMI(0x0204);
asm jnc OKgetpmiv;
return -1;
OKgetpmiv:
*sel=_CX;
*off=_DX;
return 0;
}
int SetPMinterruptVector(BYTE b,WORD sel,WORD off)
{
_BL=b;
_CX= sel;
_DX= off;
DPMI(0x0205);
asm jnc OKsetpmiv;
return -1;
OKsetpmiv:
return 0;
}
/* Memory managment services DPMI 0.9 */
void getfreeinfo(FREEMEMINFO *fm)
{
asm push es ;
_ES=FP_SEG(fm) ; _DI=FP_OFF(fm) ;
DPMI(0x500);
asm pop es ;
}
void printfreeinfo(FREEMEMINFO *fm)
{
printf("Largest available block : %lu Byte \n",fm->i1);
printf("Number free pages : %3lu = %4lu KB\n",fm->i2,fm->i2*4);
printf("Number free pages to lock : %3lu = %4lu KB\n",fm->i3,fm->i3*4);
printf("Number pages of linear addr space : %3lu = %4lu KB\n",fm->i4,fm->i4*4);
printf("Number pages not locked : %3lu = %4lu KB\n",fm->i5,fm->i5*4);
printf("Number pages not used : %3lu = %4lu KB\n",fm->i6,fm->i6*4);
printf("Number pages managed by the Dpmi : %3lu = %4lu KB\n",fm->i7,fm->i7*4);
printf("Number pages free addr space : %3lu = %4lu KB\n",fm->i8,fm->i8*4);
printf("Number pages in swapfile : %3lu = %4lu KB\n",fm->i9,fm->i9*4);
}
DWORD GlobalAlloc(DWORD bytes,DWORD *memhandle)
{
_BX=(WORD) (bytes>>16);
_CX=(WORD) bytes ;
DPMI(0x501);
asm jnc OKalloc;
return 0 ;
OKalloc:
*memhandle = (DWORD)_CX | ( (DWORD)_BX <<16 ) ;
return ( (DWORD)_DI | ( (DWORD)_SI <<16 ) );
}
int GlobalFree(DWORD handle)
{
_SI=(WORD) (handle>>16);
_DI=(WORD) handle ;
DPMI(0x0502);
asm jnc OKFREE ;
return -1 ;
OKFREE:
return 0 ;
}
/* Page locking services DPMI 0.9 */
int LockLinRegion(DWORD size,DWORD address)
{
_BX=(WORD) (address>>16);
_CX=(WORD) address;
_SI=(WORD) (size>>16);
_DI=(WORD) size;
DPMI(0x0600);
asm jnc oklocklin;
return -1;
oklocklin:
return 0;
}
int UnlockLinRegion(DWORD size,DWORD address)
{
_BX=(WORD) (address>>16);
_CX=(WORD) address;
_SI=(WORD) (size>>16);
_DI=(WORD) size;
DPMI(0x0600);
asm jnc okunlocklin;
return -1;
okunlocklin:
return 0;
}
/* Other multiplex int 2F */
void Yield() /* give control to operating system (like GetMassage) */
{
_AX=0x1680 ;
asm int 2Fh ;
}
/* Protected mode API */
DWORD lsl(WORD sel) /* load selector limit */
{
asm { db 66h;
sub ax,ax; /* sub eax,eax */
db 66h;
mov bx,ax; /* mov ebx,eax */
mov bx,sel
db 66h;
lsl ax,bx; /* lsl eax,ebx */
db 66h;
mov dx,ax ; /* mov eax,eax ax:low word */
db 66h ;
shr dx,16 /* shr edx,16 dx:high word */
}
}
WORD lsl16(WORD sel) /* 16-bit version of lsl for 80286 */
{
asm sub ax,ax
asm lsl ax,sel
return _AX ;
}
WORD lar(WORD sel) /* load access rights */
{
asm sub ax,ax ;
asm lar ax,sel;
asm shr ax,8 ;
return _AX ;
}
WORD verr(WORD sel) /* verify read */
{
asm mov ax,1 ;
asm verr sel ;
asm je okr ;
asm dec ax ;
okr:
return _AX ;
}
WORD verw(WORD sel) /* verify write */
{
asm mov ax,1 ;
asm verw sel ;
asm je okw ;
asm dec ax ;
okw:
return _AX ;
}
void sgdt(GDTR *g) /* save gdt table */
{
asm mov si,g ;
asm sgdt [si] ;
}
void sidt(GDTR *g) /* save idt table */
{
asm mov si,g ;
asm sidt [si] ;
}
WORD sldt(void) /* save ldt-selector */
{
asm sldt ax ;
return _AX ;
}
WORD str(void) /* save task-register */
{
asm str ax ;
return _AX ;
}
/* Protected mode utilities */
void far * incfp(void far *a) /* get next selector */
{
FP_SEG(a)+=SelInc();
return(a);
}
void far * decfp(void far *a) /* get previous selector */
{
FP_SEG(a)-=SelInc();
return(a);
}
void printdescriptor(DESCRIPTOR d)
{
printf("b=%02X%02X%04X lim=%01X%04X p=%u dpl=%u %s t4=%X t=%u %s %s\n",
d.base_hi,d.base_mi,d.base_lo,
d.lim_hi&15,d.lim_lo,
(d.access&128)>>7,
(d.access&96)>>5,
(d.access&16) ? "MEMseg" : "SYSseg",
(d.access&15),
(d.access&7),
(d.lim_hi & 64) ? "32bit" : "16bit" ,
(d.lim_hi & 128) ? "paging": " " );
}
void farcopy(void far *dest,void far *source,DWORD bytes)
{
unsigned long i ;
bytes++; /* if bytes %2 = 1 */
bytes>>=1;
poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
for (i=1; i< bytes ; i++) {
FP_OFF(dest)+=2 ;
if (FP_OFF(dest)==0) dest=incfp(dest);
FP_OFF(source)+=2 ;
if (FP_OFF(source)==0) source=incfp(source);
poke( FP_SEG(dest),FP_OFF(dest),peek(FP_SEG(source),FP_OFF(source)) );
}
}
/* high level C-function using DPMI-API */
/* malloc,free */
#define PAGESIZE 4096
#define PAGEBUCKET 11
#define NBUCKETS 30
#define MAGIC 0xFFF0
union overhead {
struct {
WORD page;
WORD offset;
} free ;
struct {
WORD magic ;
WORD index ;
} use ;
} ;
static union overhead nextf[NBUCKETS];
void far * morepages(WORD bucket)
{
WORD nblks,i,page,nsel,nextpage;
DWORD sz,handle,memaddress;
sz = ((DWORD)1) << (bucket + 2) ;
if (sz<PAGESIZE) /* 1st case : divide 4K-Page in sz-big blocks */
{
if ((handle=GlobalAlloc(PAGESIZE,&memaddress))==0)
return NULL ;
if ( (page=AllocLDT(1)) ==0) { /* no more selectors ? */
GlobalFree(handle); /* free memory */
return NULL;
}
if (SetBaseAddress(page,memaddress)==-1) return NULL;
if (SetLimit(page,PAGESIZE-1)==-1) return NULL;
nblks = PAGESIZE / (WORD)sz ; /* number of pieces */
nblks--;
nextf[bucket].free.page=page; /* freelist -> second block */
nextf[bucket].free.offset=sz;
for (i=1;i< (nblks);i++) /* fill header of blocks */
{
poke(page,i*sz,page);
poke(page,i*sz +2,(i+1)*sz);
}
poke(page,nblks*sz,0); /* last block -> NULL */
poke(page,nblks*sz+2,0);
}
else { /* 2.nd case : one selectors per 64 KB */
if ((handle=GlobalAlloc(sz,&memaddress))==0) return NULL ;
nsel=(WORD) ((sz-1)>>16); /* nsel = number of selectors */
nsel++;
if ((page=AllocLDT(nsel))==0) { /* no more selectors? */
GlobalFree(handle) ; /* free memory */
return NULL;
}
if (sz>0x10000L) sz=0x10000L ; /* divide in 64KB */
nextpage=page;
for (i=1;i<=nsel;i++) {
if (SetBaseAddress(nextpage,memaddress)==-1)
printf("error set Base\n");
if (SetLimit(nextpage,sz-1)==-1)
printf("error set Limit\n");
memaddress+=0x10000L ;
nextpage+=SelInc(); /* get next selector number */
}
}
return (MK_FP(page,0)) ;
}
void far *extmalloc(DWORD nbytes)
{
WORD bucket, n=0 ;
DWORD amt ;
union overhead far *fp;
if (nbytes == 0 ) return NULL;
nbytes+= sizeof(union overhead) ;
if (nbytes <= PAGESIZE ) { /* nbytes <= PAGE */
amt = 4; /* bucket = 1..12 */
bucket = 0;
n = 0 ;
}
else { /* nbytes > PAGE */
amt = PAGESIZE; /* bucket = 13..30 */
bucket = PAGEBUCKET;
n=PAGESIZE;
}
while (nbytes > amt + n) {
amt <<= 1;
if (amt == 0)
return NULL;
bucket++;
}
if (nextf[bucket].free.page == 0) { /* no mem in list */
fp=(union overhead far *)morepages(bucket);
if ((fp) == NULL) /* no mem from dpmi */
return NULL;
}
else { /* mem available in list */
/* now : nextf[] -> myblock -> nextp */
/* fp -> myblock */
fp=(union overhead far *)MK_FP(nextf[bucket].free.page,nextf[bucket].free.offset);
/* nextf[] -> nextp */
nextf[bucket].free.page =fp->free.page;
nextf[bucket].free.offset=fp->free.offset;
}
fp->use.magic= MAGIC ;
fp->use.index= bucket;
return ((void far *)(fp+1));
}
void extfree(void far *p)
{
union overhead far *fp ;
WORD bucket ;
fp=(union overhead far *)p - 1; /* get header */
if (fp->use.magic!= MAGIC) return ; /* bad pointer */
bucket = fp->use.index ; /* get size of pointer */
/* nextf[] -> nextp */
/* wanted : nextf[] -> fp -> nextf */
fp->free.page=nextf[bucket].free.page;
fp->free.offset=nextf[bucket].free.offset;
nextf[bucket].free.page = FP_SEG(fp);
nextf[bucket].free.offset=FP_OFF(fp);
}